﻿using MattDotson.GlobalToolkit;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.Practices.Unity;

namespace MattDotson.GlobalToolkit.Tests
{


    /// <summary>
    ///This is a test class for CurrencyTest and is intended
    ///to contain all CurrencyTest Unit Tests
    ///</summary>
    [TestClass()]
    public class CurrencyTest
    {

        private static IUnityContainer container = new UnityContainer();

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            //register the default currency provider as a singleton.
            container.RegisterType<ICurrencyProvider, DefaultCurrencyProvider>(new ContainerControlledLifetimeManager());
            GlobalToolkitContext.ServiceLocator = new UnityServiceLocator(container);
        }

        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for op_Inequality
        ///</summary>
        [TestMethod()]
        public void op_InequalityTest()
        {
            Currency left = new Currency(123.55m, "USD");
            Currency right = new Currency(123.44m, "USD");
            Currency other = new Currency(123.55m, "EUR");

            Assert.IsTrue(left != right);
            Assert.IsTrue(left != null);
            Assert.IsTrue(left != Currency.Empty);
            Assert.IsTrue(Currency.Empty != right);
            Assert.IsFalse(Currency.Empty != Currency.Empty);
            Assert.IsFalse(left != left);
            Assert.IsFalse(right != right);
            Assert.IsTrue(left != other);
        }

        /// <summary>
        ///A test for op_Equality
        ///</summary>
        [TestMethod()]
        public void op_EqualityTest()
        {
            Currency left = new Currency(123.55m, "USD");
            Currency right = new Currency(123.44m, "USD");
            Currency other = new Currency(123.55m, "EUR");

            Assert.IsFalse(left == right);
            Assert.IsFalse(left == null);
            Assert.IsFalse(left == Currency.Empty);
            Assert.IsFalse(Currency.Empty == right);
            Assert.IsTrue(Currency.Empty == Currency.Empty);
            Assert.IsTrue(left == left);
            Assert.IsTrue(right == right);
            Assert.IsTrue(left == new Currency(123.55m, "USD"));
            Assert.IsFalse(left == other);
        }

        /// <summary>
        ///A test for GetHashCode
        ///</summary>
        [TestMethod()]
        public void GetHashCodeTest()
        {
            Currency target = new Currency(4321.99m, "USD");
            Currency other = new Currency(4321.99m, "USD");
            Currency o2 = new Currency(4321.99m, "EUR");
            Assert.AreEqual(target.GetHashCode(), other.GetHashCode());
            Assert.AreNotEqual(target.GetHashCode(), o2.GetHashCode());
        }

        /// <summary>
        ///A test for Currency Constructor
        ///</summary>
        [TestMethod(), ExpectedException(typeof(ArgumentNullException))]
        public void CurrencyConstructorTest1()
        {
            Currency target = new Currency(-1m, (CurrencyInfo)null);
        }

        /// <summary>
        ///A test for Currency Constructor
        ///</summary>
        [TestMethod(), ExpectedException(typeof(ArgumentException))]
        public void CurrencyConstructorTest()
        {
            Decimal value = 0m;
            string isoCode = string.Empty;
            Currency target = new Currency(value, isoCode);
        }

        [TestMethod()]
        public void CurrencyUnaryTests()
        {
            Currency c1 = new Currency(123.45m, "EUR");
            Currency expected = new Currency(-123.45m, "EUR");

            Assert.AreEqual<Currency>(expected, -c1);

            Assert.AreEqual<Currency>(c1, -(-c1));

            Assert.AreEqual<Currency>(Currency.Empty, -Currency.Empty);
        }

        [TestMethod()]
        public void CurrencyArithmaticTests()
        {
            Currency c1 = new Currency(100m, "CAD");
            Currency c2 = new Currency(123m, "CAD");

            Currency expected = new Currency(223m, "CAD");
            Currency actual = c1 + c2;
            Assert.AreEqual<Currency>(expected, actual, "addition operator");

            actual = Currency.Add(c1, c2);
            Assert.AreEqual<Currency>(expected, actual, "addition static");

            actual = Currency.Empty + c1;
            Assert.AreEqual<Currency>(c1, actual);

            actual = c1 + Currency.Empty;
            Assert.AreEqual<Currency>(c1, actual);

            //subtraction
            expected = new Currency(23m, "CAD");

            actual = c2 - c1;
            Assert.AreEqual<Currency>(expected, actual, "subtraction operator");

            actual = Currency.Subtract(c2, c1);
            Assert.AreEqual<Currency>(expected, actual, "subtraction operator");

            actual = c2 - Currency.Empty;
            Assert.AreEqual<Currency>(c2, actual, "subtract empty");

            actual = Currency.Empty - c2;
            Assert.AreEqual<Currency>(-c2, actual, "subtract from empty");

            //multiplication
            expected = new Currency(200.0m, "CAD");

            actual = 2 * c1;
            Assert.AreEqual<Currency>(expected, actual, "integer multiplication");

            actual = 2f * c1;
            Assert.AreEqual<Currency>(expected, actual, "float multiplication");

            actual = 2.0 * c1;
            Assert.AreEqual<Currency>(expected, actual, "double multiplication");

            actual = 2.0m * c1;
            Assert.AreEqual<Currency>(expected, actual, "decimal multiplication");

            //division
            expected = new Currency(50.0m, "CAD");

            actual = c1 / 2;
            Assert.AreEqual<Currency>(expected, actual, "integer division");

            actual = c1 / 2f;
            Assert.AreEqual<Currency>(expected, actual, "float division");

            actual = c1 / 2.0;
            Assert.AreEqual<Currency>(expected, actual, "double division");

            actual = c1 / 2.0m;
            Assert.AreEqual<Currency>(expected, actual, "decimal division");

        }
    }
}